﻿package game.alternativa {
	import flash.display3D.Context3D;
	import flash.display.BitmapData;
	import alternativa.engine3d.core.Object3D;
	import game.objects.TextureObject;
	import alternativa.engine3d.resources.ExternalTextureResource;
	import alternativa.engine3d.resources.TextureResource;
	import alternativa.engine3d.materials.StandardMaterial;
	import alternativa.engine3d.materials.EnvironmentMaterial;
	import alternativa.engine3d.resources.BitmapTextureResource;
	import alternativa.engine3d.materials.Material;
	import alternativa.engine3d.objects.Mesh;
	import alternativa.engine3d.objects.Surface;
	import alternativa.engine3d.core.Resource;
	import alternativa.engine3d.core.VertexAttributes;
	import alternativa.engine3d.materials.VertexLightTextureMaterial;
	
	public class UtilTextures {
		
		private var context:Context3D;
		private var objects:Vector.<Object3D>;
		
		public function UtilTextures ( context:Context3D, objects:Vector.<Object3D> ):void {
			this.objects	= objects;
			this.context	= context;
		}
		
		public function set context3D ( context:Context3D ):void {
			this.context = context;
		}
		
		public function setupMaterials(materials:Object, alpha:Number = 1, reflection:Number = 0.1):void {
			if (!materials) materials = new Object();;
			
			//если нет дифуза
			if (!materials[TextureObject.DIFFUSE])
				materials[TextureObject.DIFFUSE] = getResource ( new TextureObject ( TextureObject.DIFFUSE, 0x333333 ) );
			
			//если нет бампа
			if (!materials[TextureObject.BUMP])
				materials[TextureObject.BUMP] = getResource ( new TextureObject ( TextureObject.BUMP, 0xffffff ) );
			
			//если нет прозрачности
			if (!materials[TextureObject.TRANSPARENT])
				materials[TextureObject.TRANSPARENT] = getResource ( new TextureObject ( TextureObject.TRANSPARENT, 0xffffff ) );
			
			
			//если нет коэффициента рефлекта, но есть рефлект
			if (!materials[TextureObject.REFLECTION] && materials[TextureObject.ENVIRONMENT])
				materials[TextureObject.REFLECTION] = getResource ( new TextureObject ( TextureObject.REFLECTION, 0xffffff ) );
			
			var material:Material;
			if (materials[TextureObject.ENVIRONMENT])
				material = createReflectionTexture (materials);
			else if (materials[TextureObject.SPECULAR])
				material = createStandartTexture (materials);
			else
				material = createLightTexture (materials);
				
			
			if (material) {
				if (alpha<1) {
					if (material is StandardMaterial) {
						(material as StandardMaterial).alpha			= alpha;
						(material as StandardMaterial).alphaThreshold	= 1.1;
					} else if (material is VertexLightTextureMaterial) {
						(material as VertexLightTextureMaterial).alpha			= alpha;
						(material as VertexLightTextureMaterial).alphaThreshold	= 1.1;
					}
				}
				if (reflection<1) {
					if (material is EnvironmentMaterial) {
						//(material as EnvironmentMaterial).reflection = reflection;
					}
				}
				applyMaterial(material);
				
				
			}
		}
		
		public static function getResource(object:TextureObject):TextureResource {
			var texture:TextureResource;
			if (object.url) { 
				texture = new ExternalTextureResource(object.url);
			} else if (object.color) {
				texture = new BitmapTextureResource ( new BitmapData ( 1, 1, false, object.color ) );
			} else if (object.resource) {
				texture = object.resource;
			}
			return texture;
		}
		
		private function createStandartTexture(materials:Object):StandardMaterial {
			var material:StandardMaterial =  new StandardMaterial (	materials[TextureObject.DIFFUSE],
																	materials[TextureObject.BUMP],
																	materials[TextureObject.SPECULAR],
																	materials[TextureObject.GLOSSINESS],
																	materials[TextureObject.TRANSPARENT] );
																	
			return material;
		}
		
		private function createLightTexture(materials:Object):VertexLightTextureMaterial {
			var material:VertexLightTextureMaterial =  new VertexLightTextureMaterial (	materials[TextureObject.DIFFUSE],
																						materials[TextureObject.TRANSPARENT] );
																	
			return material;
		}
		
		//var m:VertexLightTextureMaterial = new VertexLightTextureMaterial(materials[TextureObject.DIFFUSE], materials[TextureObject.TRANSPARENT]);
			
		
		private function createReflectionTexture(materials:Object):EnvironmentMaterial {
			var material:EnvironmentMaterial = new EnvironmentMaterial (	materials[TextureObject.DIFFUSE],
																			materials[TextureObject.ENVIRONMENT],
																			materials[TextureObject.BUMP],
																			materials[TextureObject.REFLECTION],
																			materials[TextureObject.LIGHT],
																			materials[TextureObject.TRANSPARENT] );
			
			/*var material:TestMaterial = new TestMaterial ( materials[TextureObject.DIFFUSE],
																			materials[TextureObject.ENVIRONMENT],
																			materials[TextureObject.BUMP],
																			materials[TextureObject.REFLECTION],
																			materials[TextureObject.LIGHT],
																			materials[TextureObject.TRANSPARENT],
																			materials[TextureObject.SPECULAR]);*/
			return material;
		}
		
		private function applyMaterial(material:Material):void {
			var objectsQuantity:uint = objects.length;
			for (var objInd:uint = 0; objInd < objectsQuantity; objInd++) {
				var mesh:Mesh = objects[objInd] as Mesh;
				
				if (mesh != null) {
					
					var meshSurfacesQuantity:uint = mesh.numSurfaces;
					for (var surfaceInd:uint = 0; surfaceInd < meshSurfacesQuantity; surfaceInd++) {
						var surface:Surface = mesh.getSurface(surfaceInd);
						surface.material = material;
						
					}
					for each (var meshResource:Resource in mesh.getResources()) {
						if (!meshResource.isUploaded)
							meshResource.upload(context);
					}
				}
				
			}
			
		}
		
	}
	
}